﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mime;
using System.Security.Cryptography.Pkcs;

namespace NHINDirect
{
    public class SignedEntity : MultipartEntity
    {
        MimeEntity m_content;
        MimeEntity m_signature;
        
        public SignedEntity(DigestAlgorithm algorithm, MimeEntity content, MimeEntity signature)
            : base(CreateContentType(algorithm))
        {
            if (content == null)
            {
                throw new ArgumentNullException();
            }
            
            this.Content = content;
            this.Signature = signature;
        }
        
        public SignedEntity(ContentType contentType, IEnumerable<MimeEntity> parts)
            : base(contentType)
        {
            if (parts == null)
            {
                throw new ArgumentNullException();
            }
            
            int count = 0;
            foreach(MimeEntity part in parts)
            {
                switch(count)
                {
                    default:
                        throw new ProtocolException(ProtocolError.InvalidSignatureMimeParts);
                    
                    case 0:
                        this.Content = part;
                        break;
                    
                    case 1:
                        this.Signature = part;
                        break;
                }                
                ++count;
            }
        }
        
        public MimeEntity Content
        {
            get
            {
                return this.m_content;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }
                
                this.m_content = value;
            }
        }
        
        public MimeEntity Signature
        {
            get
            {
                return this.m_signature;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }

                value.VerifyMediaType(Protocol.SignatureContentMediaType, Protocol.SignatureContentMediaTypeAlternative);
                value.VerifyTransferEncoding(Protocol.TransferEncodingBase64);
                this.m_signature = value;
            }
        }
                
        public override IEnumerator<MimeEntity> GetEnumerator()
        {
            yield return this.m_content;
            yield return this.m_signature;
        }
        
        public static SignedEntity Load(MimeEntity source)
        {
            if (source == null)
            {
                throw new ArgumentNullException();
            }

            if (!source.IsMultiPart)
            {
                throw new SignatureValidationException();
            }
            
            return new SignedEntity(source.ParsedContentType, source.GetParts());
        }
        
        static ContentType CreateContentType(DigestAlgorithm digestAlgorithm)
        {
            ContentType contentType = new ContentType(Protocol.MultiPartType_Signed);
            contentType.Parameters.Add("micalg", Protocol.ToString(digestAlgorithm));
            return contentType;
        }
    }
}
